<!DOCTYPE html>
<html lang="en-US">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <title>学习 lodash  源码整体架构，打造属于自己的函数式编程类库 | 若川的博客</title>
    <meta name="generator" content="VuePress 1.8.2">
    <link rel="icon" href="/favicon.ico">
    <link rel="mainfest" href="/mainfest.json">
    <meta name="description" content="若川，微信搜索「若川视野」关注我，长期交流学习。写有《学习源码整体架构系列》。包含jquery源码、underscore源码、lodash源码、sentry源码、vuex源码、axios源码、koa源码、redux源码。前端路上，PPT爱好者，所知甚少，唯善学。">
    
    <link rel="preload" href="/assets/css/0.styles.0ad39d54.css" as="style"><link rel="preload" href="/assets/js/app.9fbcafa6.js" as="script"><link rel="preload" href="/assets/js/2.33539d56.js" as="script"><link rel="preload" href="/assets/js/11.599e7eee.js" as="script"><link rel="preload" href="/assets/js/23.72249401.js" as="script"><link rel="prefetch" href="/assets/js/10.17a947d6.js"><link rel="prefetch" href="/assets/js/12.574e6f26.js"><link rel="prefetch" href="/assets/js/13.3a93edbc.js"><link rel="prefetch" href="/assets/js/14.c9f20b6b.js"><link rel="prefetch" href="/assets/js/15.c6b03e37.js"><link rel="prefetch" href="/assets/js/16.c445ccb9.js"><link rel="prefetch" href="/assets/js/17.60b94fab.js"><link rel="prefetch" href="/assets/js/18.86de3f95.js"><link rel="prefetch" href="/assets/js/19.6fedd448.js"><link rel="prefetch" href="/assets/js/20.5b11fd5b.js"><link rel="prefetch" href="/assets/js/21.e5faf0b7.js"><link rel="prefetch" href="/assets/js/22.23137eae.js"><link rel="prefetch" href="/assets/js/24.20d474b3.js"><link rel="prefetch" href="/assets/js/25.6dc03c07.js"><link rel="prefetch" href="/assets/js/26.fcf5232b.js"><link rel="prefetch" href="/assets/js/27.6ee352c4.js"><link rel="prefetch" href="/assets/js/28.7534ba1e.js"><link rel="prefetch" href="/assets/js/29.352ed61c.js"><link rel="prefetch" href="/assets/js/3.2f315ac7.js"><link rel="prefetch" href="/assets/js/30.e5dbb079.js"><link rel="prefetch" href="/assets/js/31.b8562982.js"><link rel="prefetch" href="/assets/js/32.f3c8f832.js"><link rel="prefetch" href="/assets/js/33.5ca5188e.js"><link rel="prefetch" href="/assets/js/34.624e3116.js"><link rel="prefetch" href="/assets/js/35.35a86a7c.js"><link rel="prefetch" href="/assets/js/36.21f88fe5.js"><link rel="prefetch" href="/assets/js/37.f5b01c2c.js"><link rel="prefetch" href="/assets/js/38.79ed2093.js"><link rel="prefetch" href="/assets/js/39.687f8425.js"><link rel="prefetch" href="/assets/js/4.9af06e45.js"><link rel="prefetch" href="/assets/js/40.deaa2213.js"><link rel="prefetch" href="/assets/js/41.ede9f8e5.js"><link rel="prefetch" href="/assets/js/42.c48ff846.js"><link rel="prefetch" href="/assets/js/43.012e8b81.js"><link rel="prefetch" href="/assets/js/44.d7040c40.js"><link rel="prefetch" href="/assets/js/45.2805a83b.js"><link rel="prefetch" href="/assets/js/46.95a37284.js"><link rel="prefetch" href="/assets/js/47.d1c213db.js"><link rel="prefetch" href="/assets/js/48.00be6d02.js"><link rel="prefetch" href="/assets/js/49.3d722bd1.js"><link rel="prefetch" href="/assets/js/5.aace9ee0.js"><link rel="prefetch" href="/assets/js/50.d9fa2cde.js"><link rel="prefetch" href="/assets/js/51.e0aaa97a.js"><link rel="prefetch" href="/assets/js/52.a700a7a9.js"><link rel="prefetch" href="/assets/js/53.dbb93ca1.js"><link rel="prefetch" href="/assets/js/6.e0576ee1.js"><link rel="prefetch" href="/assets/js/7.4a4a967d.js"><link rel="prefetch" href="/assets/js/8.b7698a4a.js"><link rel="prefetch" href="/assets/js/9.6930a420.js">
    <link rel="stylesheet" href="/assets/css/0.styles.0ad39d54.css">
  </head>
  <body>
    <div id="app" data-server-rendered="true"><div class="theme-container"><header class="navbar"><div class="sidebar-button"><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" role="img" viewBox="0 0 448 512" class="icon"><path fill="currentColor" d="M436 124H12c-6.627 0-12-5.373-12-12V80c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12zm0 160H12c-6.627 0-12-5.373-12-12v-32c0-6.627 5.373-12 12-12h424c6.627 0 12 5.373 12 12v32c0 6.627-5.373 12-12 12z"></path></svg></div> <a href="/" class="home-link router-link-active"><!----> <span class="site-name">若川的博客</span></a> <div class="links"><div class="search-box"><input aria-label="Search" autocomplete="off" spellcheck="false" value=""> <!----></div> <nav class="nav-links can-hide"><div class="nav-item"><a href="https://image-static.segmentfault.com/355/182/3551821948-5df888aa1dc88_articlex" target="_blank" rel="noopener noreferrer" class="nav-link external">
  公众号：若川视野
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div><div class="nav-item"><a href="/" class="nav-link">
  目录
</a></div><div class="nav-item"><a href="/about/" class="nav-link">
  关于我
</a></div><div class="nav-item"><a href="/poetry/2012-2016/" class="nav-link">
  曾经写的&quot;诗词&quot;
</a></div><div class="nav-item"><a href="https://github.com/lxchuan12/blog" target="_blank" rel="noopener noreferrer" class="nav-link external">
  Github
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div><div class="nav-item"><a href="https://juejin.im/user/1415826704971918/posts" target="_blank" rel="noopener noreferrer" class="nav-link external">
  掘金
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div><div class="nav-item"><a href="https://www.zhihu.com/people/lxchuan12/activities" target="_blank" rel="noopener noreferrer" class="nav-link external">
  知乎
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div><div class="nav-item"><a href="https://www.yuque.com/lxchuan12/blog" target="_blank" rel="noopener noreferrer" class="nav-link external">
  语雀
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="其他" class="dropdown-title"><span class="title">其他</span> <span class="arrow down"></span></button> <button type="button" aria-label="其他" class="mobile-dropdown-title"><span class="title">其他</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://segmentfault.com/u/lxchuan12/articles" target="_blank" rel="noopener noreferrer" class="nav-link external">
  segmentFault
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="http://weibo.com/lxchuan12" target="_blank" rel="noopener noreferrer" class="nav-link external">
  微博
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="http://www.jianshu.com/users/83129d433d72/latest_articles" target="_blank" rel="noopener noreferrer" class="nav-link external">
  简书
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="友链" class="dropdown-title"><span class="title">友链</span> <span class="arrow down"></span></button> <button type="button" aria-label="友链" class="mobile-dropdown-title"><span class="title">友链</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shanyue.tech" target="_blank" rel="noopener noreferrer" class="nav-link external">
  山月
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="http://lucifer.ren" target="_blank" rel="noopener noreferrer" class="nav-link external">
  lucifer
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://hungryturbo.com" target="_blank" rel="noopener noreferrer" class="nav-link external">
  童欧巴
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://www.scarsu.com/" target="_blank" rel="noopener noreferrer" class="nav-link external">
  scarsu
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://mtc.nofwl.com/" target="_blank" rel="noopener noreferrer" class="nav-link external">
  lencx的博客
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://coder.itclan.cn/" target="_blank" rel="noopener noreferrer" class="nav-link external">
  itclanCoder
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://ruizhengyun.cn" target="_blank" rel="noopener noreferrer" class="nav-link external">
  编程之上
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div> <!----></nav></div></header> <div class="sidebar-mask"></div> <aside class="sidebar"><nav class="nav-links"><div class="nav-item"><a href="https://image-static.segmentfault.com/355/182/3551821948-5df888aa1dc88_articlex" target="_blank" rel="noopener noreferrer" class="nav-link external">
  公众号：若川视野
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div><div class="nav-item"><a href="/" class="nav-link">
  目录
</a></div><div class="nav-item"><a href="/about/" class="nav-link">
  关于我
</a></div><div class="nav-item"><a href="/poetry/2012-2016/" class="nav-link">
  曾经写的&quot;诗词&quot;
</a></div><div class="nav-item"><a href="https://github.com/lxchuan12/blog" target="_blank" rel="noopener noreferrer" class="nav-link external">
  Github
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div><div class="nav-item"><a href="https://juejin.im/user/1415826704971918/posts" target="_blank" rel="noopener noreferrer" class="nav-link external">
  掘金
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div><div class="nav-item"><a href="https://www.zhihu.com/people/lxchuan12/activities" target="_blank" rel="noopener noreferrer" class="nav-link external">
  知乎
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div><div class="nav-item"><a href="https://www.yuque.com/lxchuan12/blog" target="_blank" rel="noopener noreferrer" class="nav-link external">
  语雀
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="其他" class="dropdown-title"><span class="title">其他</span> <span class="arrow down"></span></button> <button type="button" aria-label="其他" class="mobile-dropdown-title"><span class="title">其他</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://segmentfault.com/u/lxchuan12/articles" target="_blank" rel="noopener noreferrer" class="nav-link external">
  segmentFault
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="http://weibo.com/lxchuan12" target="_blank" rel="noopener noreferrer" class="nav-link external">
  微博
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="http://www.jianshu.com/users/83129d433d72/latest_articles" target="_blank" rel="noopener noreferrer" class="nav-link external">
  简书
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div><div class="nav-item"><div class="dropdown-wrapper"><button type="button" aria-label="友链" class="dropdown-title"><span class="title">友链</span> <span class="arrow down"></span></button> <button type="button" aria-label="友链" class="mobile-dropdown-title"><span class="title">友链</span> <span class="arrow right"></span></button> <ul class="nav-dropdown" style="display:none;"><li class="dropdown-item"><!----> <a href="https://shanyue.tech" target="_blank" rel="noopener noreferrer" class="nav-link external">
  山月
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="http://lucifer.ren" target="_blank" rel="noopener noreferrer" class="nav-link external">
  lucifer
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://hungryturbo.com" target="_blank" rel="noopener noreferrer" class="nav-link external">
  童欧巴
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://www.scarsu.com/" target="_blank" rel="noopener noreferrer" class="nav-link external">
  scarsu
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://mtc.nofwl.com/" target="_blank" rel="noopener noreferrer" class="nav-link external">
  lencx的博客
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://coder.itclan.cn/" target="_blank" rel="noopener noreferrer" class="nav-link external">
  itclanCoder
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li><li class="dropdown-item"><!----> <a href="https://ruizhengyun.cn" target="_blank" rel="noopener noreferrer" class="nav-link external">
  编程之上
  <span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></li></ul></div></div> <!----></nav>  <ul class="sidebar-links"><li><a href="/" aria-current="page" class="sidebar-link">目录</a></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading open"><span>学习源码系列</span> <span class="arrow down"></span></p> <ul class="sidebar-links sidebar-group-items"><li><a href="/redux/" class="sidebar-link">学习 redux 源码整体架构，深入理解 redux 及其中间件原理</a></li><li><a href="/koa/" class="sidebar-link">学习 koa 源码的整体架构，浅析koa洋葱模型原理和co原理</a></li><li><a href="/axios/" class="sidebar-link">学习 axios 源码整体架构，打造属于自己的请求库</a></li><li><a href="/vuex/" class="sidebar-link">学习 vuex 源码整体架构，打造属于自己的状态管理库</a></li><li><a href="/sentry/" class="sidebar-link">学习 sentry 源码整体架构，打造属于自己的前端异常监控SDK</a></li><li><a href="/lodash/" aria-current="page" class="active sidebar-link">学习 lodash  源码整体架构，打造属于自己的函数式编程类库</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/lodash/#_1-前言" class="sidebar-link">1. 前言</a></li><li class="sidebar-sub-header"><a href="/lodash/#_2-匿名函数执行" class="sidebar-link">2. 匿名函数执行</a></li><li class="sidebar-sub-header"><a href="/lodash/#_3-runincontext-函数" class="sidebar-link">3. runInContext 函数</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/lodash/#_3-1-lodashwrapper-函数" class="sidebar-link">3.1 LodashWrapper 函数</a></li><li class="sidebar-sub-header"><a href="/lodash/#_3-2-basecreate-原型继承" class="sidebar-link">3.2 baseCreate 原型继承</a></li><li class="sidebar-sub-header"><a href="/lodash/#_3-3-object-create-用法举例" class="sidebar-link">3.3 Object.create() 用法举例</a></li></ul></li><li class="sidebar-sub-header"><a href="/lodash/#_4-mixin" class="sidebar-link">4. mixin</a><ul class="sidebar-sub-headers"><li class="sidebar-sub-header"><a href="/lodash/#_4-1-mixin-具体用法" class="sidebar-link">4.1 mixin 具体用法</a></li><li class="sidebar-sub-header"><a href="/lodash/#_4-2-mixin-源码" class="sidebar-link">4.2 mixin 源码</a></li><li class="sidebar-sub-header"><a href="/lodash/#_4-3-mixin-衍生的函数-keys" class="sidebar-link">4.3 mixin 衍生的函数 keys</a></li><li class="sidebar-sub-header"><a href="/lodash/#_4-4-mixin-衍生的函数-basefunctions" class="sidebar-link">4.4 mixin 衍生的函数 baseFunctions</a></li><li class="sidebar-sub-header"><a href="/lodash/#_4-5-mixin-衍生的函数-isfunction" class="sidebar-link">4.5 mixin 衍生的函数 isFunction</a></li><li class="sidebar-sub-header"><a href="/lodash/#_4-6-mixin-衍生的函数-arrayeach" class="sidebar-link">4.6 mixin 衍生的函数 arrayEach</a></li><li class="sidebar-sub-header"><a href="/lodash/#_4-7-mixin-衍生的函数-arraypush" class="sidebar-link">4.7 mixin 衍生的函数 arrayPush</a></li><li class="sidebar-sub-header"><a href="/lodash/#_4-8-mixin-衍生的函数-copyarray" class="sidebar-link">4.8 mixin 衍生的函数 copyArray</a></li><li class="sidebar-sub-header"><a href="/lodash/#_4-9-mixin-源码解析" class="sidebar-link">4.9 mixin 源码解析</a></li></ul></li><li class="sidebar-sub-header"><a href="/lodash/#_5-lodash-究竟在-和-prototype挂载了多少方法和属性" class="sidebar-link">5. lodash 究竟在和.prototype挂载了多少方法和属性</a></li><li class="sidebar-sub-header"><a href="/lodash/#_6-请出贯穿下文的简单的例子" class="sidebar-link">6. 请出贯穿下文的简单的例子</a></li><li class="sidebar-sub-header"><a href="/lodash/#_7-添加-lazywrapper-的方法到-lodash-prototype" class="sidebar-link">7. 添加 LazyWrapper 的方法到 lodash.prototype</a></li><li class="sidebar-sub-header"><a href="/lodash/#_8-lodash-prototype-value-即-wrappervalue" class="sidebar-link">8. lodash.prototype.value 即 wrapperValue</a></li><li class="sidebar-sub-header"><a href="/lodash/#_9-lazywrapper-prototype-value-即-lazyvalue-惰性求值" class="sidebar-link">9. LazyWrapper.prototype.value 即 lazyValue 惰性求值</a></li><li class="sidebar-sub-header"><a href="/lodash/#_10-总结" class="sidebar-link">10. 总结</a></li><li class="sidebar-sub-header"><a href="/lodash/#_11-推荐阅读" class="sidebar-link">11. 推荐阅读</a></li><li class="sidebar-sub-header"><a href="/lodash/#笔者往期文章" class="sidebar-link">笔者往期文章</a></li><li class="sidebar-sub-header"><a href="/lodash/#关于" class="sidebar-link">关于</a></li><li class="sidebar-sub-header"><a href="/lodash/#微信公众号-若川视野" class="sidebar-link">微信公众号  若川视野</a></li></ul></li><li><a href="/underscore/" class="sidebar-link">学习underscore源码整体架构，打造属于自己的函数式编程类库</a></li><li><a href="/jquery/" class="sidebar-link">学习 jQuery 源码整体架构，打造属于自己的 js 类库</a></li></ul></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>面试官问系列</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>历史文章</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>杂文</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>曾经写的&quot;诗词&quot;</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>年度总结</span> <span class="arrow right"></span></p> <!----></section></li><li><section class="sidebar-group collapsable depth-0"><p class="sidebar-heading"><span>关于</span> <span class="arrow right"></span></p> <!----></section></li></ul> </aside> <main class="page"> <div class="theme-default-content content__default"><h1 id="学习-lodash-源码整体架构-打造属于自己的函数式编程类库"><a href="#学习-lodash-源码整体架构-打造属于自己的函数式编程类库" class="header-anchor">#</a> 学习 lodash  源码整体架构，打造属于自己的函数式编程类库</h1> <h2 id="_1-前言"><a href="#_1-前言" class="header-anchor">#</a> 1. 前言</h2> <blockquote><p>你好，我是<a href="https://lxchuan12.gitee.io" target="_blank" rel="noopener noreferrer">若川<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a>，微信搜索<a href="https://mp.weixin.qq.com/s/c3hFML3XN9KCUetDOZd-DQ" target="_blank" rel="noopener noreferrer">「若川视野」<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a>关注我，专注前端技术分享。欢迎加我微信<code>ruochuan12</code>，加群交流学习。</p></blockquote> <blockquote><p>这是<code>学习源码整体架构系列</code>第三篇。整体架构这词语好像有点大，姑且就算是源码整体结构吧，主要就是学习是代码整体结构，不深究其他不是主线的具体函数的实现。文章学习的是打包整合后的代码，不是实际仓库中的拆分的代码。</p></blockquote> <blockquote><p><a href="https://github.com/lxchuan12/lodash-analysis.git" target="_blank" rel="noopener noreferrer">本文仓库地址<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a>：<code>git clone https://github.com/lxchuan12/lodash-analysis.git</code></p></blockquote> <blockquote><p><strong>要是有人说到怎么读源码，正在读文章的你能推荐我的源码系列文章，那真是太好了</strong>。</p></blockquote> <p><code>学习源码整体架构系列</code>文章如下：</p> <blockquote><p>1.<a href="https://juejin.im/post/5d39d2cbf265da1bc23fbd42" target="_blank" rel="noopener noreferrer">学习 jQuery 源码整体架构，打造属于自己的 js 类库<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a><br>
2.<a href="https://juejin.im/post/5d4bf94de51d453bb13b65dc" target="_blank" rel="noopener noreferrer">学习 underscore 源码整体架构，打造属于自己的函数式编程类库<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a><br>
3.<a href="https://juejin.im/post/5d767e1d6fb9a06b032025ea" target="_blank" rel="noopener noreferrer">学习 lodash 源码整体架构，打造属于自己的函数式编程类库<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a><br>
4.<a href="https://juejin.im/post/5dba5a39e51d452a2378348a" target="_blank" rel="noopener noreferrer">学习 sentry 源码整体架构，打造属于自己的前端异常监控SDK<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a><br>
5.<a href="https://juejin.im/post/5dd4e61a6fb9a05a5c010af0" target="_blank" rel="noopener noreferrer">学习 vuex 源码整体架构，打造属于自己的状态管理库<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a><br>
6.<a href="https://juejin.im/post/5df349b5518825123751ba66" target="_blank" rel="noopener noreferrer">学习 axios 源码整体架构，打造属于自己的请求库<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a><br>
7.<a href="https://juejin.im/post/5e69925cf265da571e262fe6" target="_blank" rel="noopener noreferrer">学习 koa 源码的整体架构，浅析koa洋葱模型原理和co原理<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a><br>
8.<a href="https://juejin.im/post/5ee63b7d51882542fc6265ad" target="_blank" rel="noopener noreferrer">学习 redux 源码整体架构，深入理解 redux 及其中间件原理<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></p></blockquote> <p>感兴趣的读者可以点击阅读。<br>
其他源码计划中的有：<a href="https://github.com/lxchuan12/express-analysis" target="_blank" rel="noopener noreferrer"><code>express</code><span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a>、<a href="https://github.com/lxchuan12/vue-router-analysis" target="_blank" rel="noopener noreferrer"><code>vue-rotuer</code><span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a>、<a href="https://github.com/lxchuan12/react-redux-analysis" target="_blank" rel="noopener noreferrer"><code>react-redux</code><span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a> 等源码，不知何时能写完（哭泣），欢迎持续关注我（若川）。</p> <p>源码类文章，一般阅读量不高。已经有能力看懂的，自己就看了。不想看，不敢看的就不会去看源码。<br>
所以我的文章，尽量写得让想看源码又不知道怎么看的读者能看懂。</p> <p><code>underscore</code>源码分析的文章比较多，而<code>lodash</code>源码分析的文章比较少。原因之一可能是由于<code>lodash</code>源码行数太多。注释加起来一万多行。</p> <p>分析<code>lodash</code>整体代码结构的文章比较少，笔者利用谷歌、必应、<code>github</code>等搜索都没有找到，可能是找的方式不对。于是打算自己写一篇。平常开发大多数人都会使用<code>lodash</code>，而且都或多或少知道，<code>lodash</code>比<code>underscore</code>性能好，性能好的主要原因是使用了惰性求值这一特性。</p> <p>本文章学习的<code>lodash</code>的版本是：<code>v4.17.15</code>。<code>unpkg.com</code>地址 https://unpkg.com/lodash@4.17.15/lodash.js</p> <p>文章篇幅可能比较长，可以先收藏再看，所以笔者使用了展开收缩的形式。</p> <p><strong>导读：</strong></p> <blockquote><p>文章主要学习了<code>runInContext()</code> 导出<code>_</code> <code>lodash</code>函数使用<code>baseCreate</code>方法原型继承<code>LodashWrapper</code>和<code>LazyWrapper</code>，<code>mixin</code>挂载方法到<code>lodash.prototype</code>、后文用结合例子解释<code>lodash.prototype.value(wrapperValue)</code>和<code>Lazy.prototype.value(lazyValue)</code>惰性求值的源码具体实现。</p></blockquote> <h2 id="_2-匿名函数执行"><a href="#_2-匿名函数执行" class="header-anchor">#</a> 2. 匿名函数执行</h2> <div class="language-js extra-class"><pre class="language-js"><code><span class="token punctuation">;</span><span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>

<span class="token punctuation">}</span><span class="token punctuation">.</span><span class="token function">call</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><p>暴露 lodash</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">var</span> _ <span class="token operator">=</span> <span class="token function">runInContext</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><h2 id="_3-runincontext-函数"><a href="#_3-runincontext-函数" class="header-anchor">#</a> 3. runInContext 函数</h2> <p>这里的简版源码，只关注函数入口和返回值。</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">var</span> runInContext <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token function">runInContext</span><span class="token punctuation">(</span><span class="token parameter">context</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
	<span class="token comment">// 浏览器中处理context为window</span>
	<span class="token comment">// ...</span>
	<span class="token keyword">function</span> <span class="token function">lodash</span><span class="token punctuation">(</span><span class="token parameter">value</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">{</span>
		<span class="token comment">// ...</span>
		<span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">LodashWrapper</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token punctuation">}</span>
	<span class="token comment">// ...</span>
	<span class="token keyword">return</span> lodash<span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><p>可以看到申明了一个<code>runInContext</code>函数。里面有一个<code>lodash</code>函数，最后处理返回这个<code>lodash</code>函数。</p> <p>再看<code>lodash</code>函数中的返回值 <code>new LodashWrapper(value)</code>。</p> <h3 id="_3-1-lodashwrapper-函数"><a href="#_3-1-lodashwrapper-函数" class="header-anchor">#</a> 3.1 LodashWrapper 函数</h3> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">function</span> <span class="token function">LodashWrapper</span><span class="token punctuation">(</span><span class="token parameter">value<span class="token punctuation">,</span> chainAll</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
	<span class="token keyword">this</span><span class="token punctuation">.</span>__wrapped__ <span class="token operator">=</span> value<span class="token punctuation">;</span>
	<span class="token keyword">this</span><span class="token punctuation">.</span>__actions__ <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
	<span class="token keyword">this</span><span class="token punctuation">.</span>__chain__ <span class="token operator">=</span> <span class="token operator">!</span><span class="token operator">!</span>chainAll<span class="token punctuation">;</span>
	<span class="token keyword">this</span><span class="token punctuation">.</span>__index__ <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
	<span class="token keyword">this</span><span class="token punctuation">.</span>__values__ <span class="token operator">=</span> <span class="token keyword">undefined</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><p>设置了这些属性：</p> <p><code>__wrapped__</code>：存放参数<code>value</code>。</p> <p><code>__actions__</code>：存放待执行的函数体<code>func</code>， 函数参数 <code>args</code>，函数执行的<code>this</code> 指向 <code>thisArg</code>。</p> <p><code>__chain__</code>、<code>undefined</code>两次取反转成布尔值<code>false</code>，不支持链式调用。和<code>underscore</code>一样，默认是不支持链式调用的。</p> <p><code>__index__</code>：索引值 默认 0。</p> <p><code>__values__</code>：主要<code>clone</code>时使用。</p> <p>接着往下搜索源码，<code>LodashWrapper</code>，
会发现这两行代码。</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token class-name">LodashWrapper</span><span class="token punctuation">.</span>prototype <span class="token operator">=</span> <span class="token function">baseCreate</span><span class="token punctuation">(</span>baseLodash<span class="token punctuation">.</span>prototype<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token class-name">LodashWrapper</span><span class="token punctuation">.</span>prototype<span class="token punctuation">.</span>constructor <span class="token operator">=</span> LodashWrapper<span class="token punctuation">;</span>
</code></pre></div><p>接着往上找<code>baseCreate、baseLodash</code>这两个函数。</p> <h3 id="_3-2-basecreate-原型继承"><a href="#_3-2-basecreate-原型继承" class="header-anchor">#</a> 3.2 baseCreate 原型继承</h3> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">//  立即执行匿名函数</span>
<span class="token comment">// 返回一个函数，用于设置原型 可以理解为是 __proto__</span>
<span class="token keyword">var</span> baseCreate <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
	<span class="token comment">// 这句放在函数外，是为了不用每次调用baseCreate都重复申明 object</span>
	<span class="token comment">// underscore 源码中，把这句放在开头就申明了一个空函数 `Ctor`</span>
	<span class="token keyword">function</span> <span class="token function">object</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
	<span class="token keyword">return</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">proto</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
		<span class="token comment">// 如果传入的参数不是object也不是function 是null</span>
		<span class="token comment">// 则返回空对象。</span>
		<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token function">isObject</span><span class="token punctuation">(</span>proto<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
			<span class="token keyword">return</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">;</span>
		<span class="token punctuation">}</span>
		<span class="token comment">// 如果支持Object.create方法，则返回 Object.create</span>
		<span class="token keyword">if</span> <span class="token punctuation">(</span>objectCreate<span class="token punctuation">)</span> <span class="token punctuation">{</span>
			<span class="token comment">// Object.create</span>
			<span class="token keyword">return</span> <span class="token function">objectCreate</span><span class="token punctuation">(</span>proto<span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token punctuation">}</span>
		<span class="token comment">// 如果不支持Object.create 用 ployfill new</span>
		object<span class="token punctuation">.</span>prototype <span class="token operator">=</span> proto<span class="token punctuation">;</span>
		<span class="token keyword">var</span> result <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">object</span><span class="token punctuation">;</span>
		<span class="token comment">// 还原 prototype</span>
		object<span class="token punctuation">.</span>prototype <span class="token operator">=</span> <span class="token keyword">undefined</span><span class="token punctuation">;</span>
		<span class="token keyword">return</span> result<span class="token punctuation">;</span>
	<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">// 空函数</span>
<span class="token keyword">function</span> <span class="token function">baseLodash</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
	<span class="token comment">// No operation performed.</span>
<span class="token punctuation">}</span>

<span class="token comment">// Ensure wrappers are instances of `baseLodash`.</span>
lodash<span class="token punctuation">.</span>prototype <span class="token operator">=</span> baseLodash<span class="token punctuation">.</span>prototype<span class="token punctuation">;</span>
<span class="token comment">// 为什么会有这一句？因为上一句把lodash.prototype.construtor 设置为Object了。这一句修正constructor</span>
lodash<span class="token punctuation">.</span>prototype<span class="token punctuation">.</span>constructor <span class="token operator">=</span> lodash<span class="token punctuation">;</span>

<span class="token class-name">LodashWrapper</span><span class="token punctuation">.</span>prototype <span class="token operator">=</span> <span class="token function">baseCreate</span><span class="token punctuation">(</span>baseLodash<span class="token punctuation">.</span>prototype<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token class-name">LodashWrapper</span><span class="token punctuation">.</span>prototype<span class="token punctuation">.</span>constructor <span class="token operator">=</span> LodashWrapper<span class="token punctuation">;</span>
</code></pre></div><p>笔者画了一张图，表示这个关系。
<img src="/assets/img/lodash-v4.17.15-prototype.051978d0.png" alt="lodash 原型关系图"></p> <h4 id="_3-2-1-衍生的-isobject-函数"><a href="#_3-2-1-衍生的-isobject-函数" class="header-anchor">#</a> 3.2.1 衍生的 isObject 函数</h4> <p>判断<code>typeof value</code>不等于<code>null</code>，并且是<code>object</code>或者<code>function</code>。</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">function</span> <span class="token function">isObject</span><span class="token punctuation">(</span><span class="token parameter">value</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
	<span class="token keyword">var</span> type <span class="token operator">=</span> <span class="token keyword">typeof</span> value<span class="token punctuation">;</span>
	<span class="token keyword">return</span> value <span class="token operator">!=</span> <span class="token keyword">null</span> <span class="token operator">&amp;&amp;</span> <span class="token punctuation">(</span>type <span class="token operator">==</span> <span class="token string">'object'</span> <span class="token operator">||</span> type <span class="token operator">==</span> <span class="token string">'function'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><h3 id="_3-3-object-create-用法举例"><a href="#_3-3-object-create-用法举例" class="header-anchor">#</a> 3.3 Object.create() 用法举例</h3> <p><a href="https://juejin.im/post/5bde7c926fb9a049f66b8b52" target="_blank" rel="noopener noreferrer">面试官问：能否模拟实现JS的new操作符<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a> 之前这篇文章写过的一段，所以这里收缩起来了。
</p><details><summary> 点击 查看 Object.create() 用法举例</summary><p></p> <p>笔者之前整理的一篇文章中也有讲过，可以翻看<a href="https://segmentfault.com/a/1190000010753942" target="_blank" rel="noopener noreferrer">JavaScript 对象所有API解析<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></p> <p><a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/create" target="_blank" rel="noopener noreferrer">MDN Object.create()<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></p> <p><code>Object.create(proto, [propertiesObject])</code>
方法创建一个新对象，使用现有的对象来提供新创建的对象的__proto__。
它接收两个参数，不过第二个可选参数是属性描述符（不常用，默认是<code>undefined</code>）。</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">var</span> anotherObject <span class="token operator">=</span> <span class="token punctuation">{</span>
    name<span class="token operator">:</span> <span class="token string">'若川'</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> myObject <span class="token operator">=</span> Object<span class="token punctuation">.</span><span class="token function">create</span><span class="token punctuation">(</span>anotherObject<span class="token punctuation">,</span> <span class="token punctuation">{</span>
    age<span class="token operator">:</span> <span class="token punctuation">{</span>
        value：<span class="token number">18</span><span class="token punctuation">,</span>
    <span class="token punctuation">}</span><span class="token punctuation">,</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 获得它的原型</span>
Object<span class="token punctuation">.</span><span class="token function">getPrototypeOf</span><span class="token punctuation">(</span>anotherObject<span class="token punctuation">)</span> <span class="token operator">===</span> <span class="token class-name">Object</span><span class="token punctuation">.</span>prototype<span class="token punctuation">;</span> <span class="token comment">// true 说明anotherObject的原型是Object.prototype</span>
Object<span class="token punctuation">.</span><span class="token function">getPrototypeOf</span><span class="token punctuation">(</span>myObject<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// {name: &quot;若川&quot;} // 说明myObject的原型是{name: &quot;若川&quot;}</span>
myObject<span class="token punctuation">.</span><span class="token function">hasOwnProperty</span><span class="token punctuation">(</span><span class="token string">'name'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// false; 说明name是原型上的。</span>
myObject<span class="token punctuation">.</span><span class="token function">hasOwnProperty</span><span class="token punctuation">(</span><span class="token string">'age'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// true 说明age是自身的</span>
myObject<span class="token punctuation">.</span>name<span class="token punctuation">;</span> <span class="token comment">// '若川'</span>
myObject<span class="token punctuation">.</span>age<span class="token punctuation">;</span> <span class="token comment">// 18;</span>
</code></pre></div><p>对于不支持<code>ES5</code>的浏览器，<code>MDN</code>上提供了<code>ployfill</code>方案。</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">typeof</span> Object<span class="token punctuation">.</span>create <span class="token operator">!==</span> <span class="token string">&quot;function&quot;</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
    Object<span class="token punctuation">.</span><span class="token function-variable function">create</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">proto<span class="token punctuation">,</span> propertiesObject</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">typeof</span> proto <span class="token operator">!==</span> <span class="token string">'object'</span> <span class="token operator">&amp;&amp;</span> <span class="token keyword">typeof</span> proto <span class="token operator">!==</span> <span class="token string">'function'</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">TypeError</span><span class="token punctuation">(</span><span class="token string">'Object prototype may only be an Object: '</span> <span class="token operator">+</span> proto<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>proto <span class="token operator">===</span> <span class="token keyword">null</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
            <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">Error</span><span class="token punctuation">(</span><span class="token string">&quot;This browser's implementation of Object.create is a shim and doesn't support 'null' as the first argument.&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">}</span>

        <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">typeof</span> propertiesObject <span class="token operator">!=</span> <span class="token string">'undefined'</span><span class="token punctuation">)</span> <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">Error</span><span class="token punctuation">(</span><span class="token string">&quot;This browser's implementation of Object.create is a shim and doesn't support a second argument.&quot;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

        <span class="token keyword">function</span> <span class="token constant">F</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span>
        <span class="token class-name">F</span><span class="token punctuation">.</span>prototype <span class="token operator">=</span> proto<span class="token punctuation">;</span>
        <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">F</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div></details> <p><code>lodash</code>上有很多方法和属性，但在<code>lodash.prototype</code>也有很多与<code>lodash</code>上相同的方法。肯定不是在<code>lodash.prototype</code>上重新写一遍。而是通过<code>mixin</code>挂载的。</p> <h2 id="_4-mixin"><a href="#_4-mixin" class="header-anchor">#</a> 4. mixin</h2> <h3 id="_4-1-mixin-具体用法"><a href="#_4-1-mixin-具体用法" class="header-anchor">#</a> 4.1 mixin 具体用法</h3> <div class="language-js extra-class"><pre class="language-js"><code>_<span class="token punctuation">.</span><span class="token function">mixin</span><span class="token punctuation">(</span><span class="token punctuation">[</span>object<span class="token operator">=</span>lodash<span class="token punctuation">]</span><span class="token punctuation">,</span> source<span class="token punctuation">,</span> <span class="token punctuation">[</span>options<span class="token operator">=</span><span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
</code></pre></div><blockquote><p>添加来源对象自身的所有可枚举函数属性到目标对象。 如果 object 是个函数，那么函数方法将被添加到原型链上。</p></blockquote> <blockquote><p>注意: 使用 _.runInContext 来创建原始的 lodash 函数来避免修改造成的冲突。</p></blockquote> <p><strong>添加版本</strong></p> <blockquote><p>0.1.0</p></blockquote> <p><strong>参数</strong></p> <blockquote><p>[object=lodash] (Function|Object): 目标对象。</p></blockquote> <blockquote><p>source (Object): 来源对象。</p></blockquote> <blockquote><p>[options={}] (Object): 选项对象。</p></blockquote> <blockquote><p>[options.chain=true] (boolean): 是否开启链式操作。</p></blockquote> <p><strong>返回</strong></p> <blockquote><p>(*): 返回 object.</p></blockquote> <h3 id="_4-2-mixin-源码"><a href="#_4-2-mixin-源码" class="header-anchor">#</a> 4.2 mixin 源码</h3> <details><summary>点击这里展开mixin源码，后文注释解析</summary> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">function</span> <span class="token function">mixin</span><span class="token punctuation">(</span><span class="token parameter">object<span class="token punctuation">,</span> source<span class="token punctuation">,</span> options</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
	<span class="token keyword">var</span> props <span class="token operator">=</span> <span class="token function">keys</span><span class="token punctuation">(</span>source<span class="token punctuation">)</span><span class="token punctuation">,</span>
		methodNames <span class="token operator">=</span> <span class="token function">baseFunctions</span><span class="token punctuation">(</span>source<span class="token punctuation">,</span> props<span class="token punctuation">)</span><span class="token punctuation">;</span>

	<span class="token keyword">if</span> <span class="token punctuation">(</span>options <span class="token operator">==</span> <span class="token keyword">null</span> <span class="token operator">&amp;&amp;</span>
		<span class="token operator">!</span><span class="token punctuation">(</span><span class="token function">isObject</span><span class="token punctuation">(</span>source<span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span> <span class="token punctuation">(</span>methodNames<span class="token punctuation">.</span>length <span class="token operator">||</span> <span class="token operator">!</span>props<span class="token punctuation">.</span>length<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
		options <span class="token operator">=</span> source<span class="token punctuation">;</span>
		source <span class="token operator">=</span> object<span class="token punctuation">;</span>
		object <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">;</span>
		methodNames <span class="token operator">=</span> <span class="token function">baseFunctions</span><span class="token punctuation">(</span>source<span class="token punctuation">,</span> <span class="token function">keys</span><span class="token punctuation">(</span>source<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token punctuation">}</span>
	<span class="token keyword">var</span> chain <span class="token operator">=</span> <span class="token operator">!</span><span class="token punctuation">(</span><span class="token function">isObject</span><span class="token punctuation">(</span>options<span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span> <span class="token string">'chain'</span> <span class="token keyword">in</span> options<span class="token punctuation">)</span> <span class="token operator">||</span> <span class="token operator">!</span><span class="token operator">!</span>options<span class="token punctuation">.</span>chain<span class="token punctuation">,</span>
		isFunc <span class="token operator">=</span> <span class="token function">isFunction</span><span class="token punctuation">(</span>object<span class="token punctuation">)</span><span class="token punctuation">;</span>

	<span class="token function">arrayEach</span><span class="token punctuation">(</span>methodNames<span class="token punctuation">,</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">methodName</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
		<span class="token keyword">var</span> func <span class="token operator">=</span> source<span class="token punctuation">[</span>methodName<span class="token punctuation">]</span><span class="token punctuation">;</span>
		object<span class="token punctuation">[</span>methodName<span class="token punctuation">]</span> <span class="token operator">=</span> func<span class="token punctuation">;</span>
		<span class="token keyword">if</span> <span class="token punctuation">(</span>isFunc<span class="token punctuation">)</span> <span class="token punctuation">{</span>
			object<span class="token punctuation">.</span>prototype<span class="token punctuation">[</span>methodName<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
				<span class="token keyword">var</span> chainAll <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>__chain__<span class="token punctuation">;</span>
				<span class="token keyword">if</span> <span class="token punctuation">(</span>chain <span class="token operator">||</span> chainAll<span class="token punctuation">)</span> <span class="token punctuation">{</span>
					<span class="token keyword">var</span> result <span class="token operator">=</span> <span class="token function">object</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>__wrapped__<span class="token punctuation">)</span><span class="token punctuation">,</span>
						actions <span class="token operator">=</span> result<span class="token punctuation">.</span>__actions__ <span class="token operator">=</span> <span class="token function">copyArray</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>__actions__<span class="token punctuation">)</span><span class="token punctuation">;</span>

					actions<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token punctuation">{</span> <span class="token string">'func'</span><span class="token operator">:</span> func<span class="token punctuation">,</span> <span class="token string">'args'</span><span class="token operator">:</span> arguments<span class="token punctuation">,</span> <span class="token string">'thisArg'</span><span class="token operator">:</span> object <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
					result<span class="token punctuation">.</span>__chain__ <span class="token operator">=</span> chainAll<span class="token punctuation">;</span>
					<span class="token keyword">return</span> result<span class="token punctuation">;</span>
				<span class="token punctuation">}</span>
				<span class="token keyword">return</span> <span class="token function">func</span><span class="token punctuation">.</span><span class="token function">apply</span><span class="token punctuation">(</span>object<span class="token punctuation">,</span> <span class="token function">arrayPush</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">value</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">]</span><span class="token punctuation">,</span> arguments<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
			<span class="token punctuation">}</span><span class="token punctuation">;</span>
		<span class="token punctuation">}</span>
	<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

	<span class="token keyword">return</span> object<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div></details>
接下来先看衍生的函数。
<p><strong>其实看到具体定义的函数代码就大概知道这个函数的功能。为了不影响主线，导致文章篇幅过长。具体源码在这里就不展开。</strong></p> <p>感兴趣的读者可以自行看这些函数衍生的其他函数的源码。</p> <h3 id="_4-3-mixin-衍生的函数-keys"><a href="#_4-3-mixin-衍生的函数-keys" class="header-anchor">#</a> 4.3 mixin 衍生的函数 keys</h3> <p>在 <code>mixin</code> 函数中 其实最终调用的就是 <code>Object.keys</code></p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">function</span> <span class="token function">keys</span><span class="token punctuation">(</span><span class="token parameter">object</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
	<span class="token keyword">return</span> <span class="token function">isArrayLike</span><span class="token punctuation">(</span>object<span class="token punctuation">)</span> <span class="token operator">?</span> <span class="token function">arrayLikeKeys</span><span class="token punctuation">(</span>object<span class="token punctuation">)</span> <span class="token operator">:</span> <span class="token function">baseKeys</span><span class="token punctuation">(</span>object<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><h3 id="_4-4-mixin-衍生的函数-basefunctions"><a href="#_4-4-mixin-衍生的函数-basefunctions" class="header-anchor">#</a> 4.4 mixin 衍生的函数 baseFunctions</h3> <p>返回函数数组集合</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">function</span> <span class="token function">baseFunctions</span><span class="token punctuation">(</span><span class="token parameter">object<span class="token punctuation">,</span> props</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
	<span class="token keyword">return</span> <span class="token function">arrayFilter</span><span class="token punctuation">(</span>props<span class="token punctuation">,</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">key</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
		<span class="token keyword">return</span> <span class="token function">isFunction</span><span class="token punctuation">(</span>object<span class="token punctuation">[</span>key<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><h3 id="_4-5-mixin-衍生的函数-isfunction"><a href="#_4-5-mixin-衍生的函数-isfunction" class="header-anchor">#</a> 4.5 mixin 衍生的函数 isFunction</h3> <p>判断参数是否是函数</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">function</span> <span class="token function">isFunction</span><span class="token punctuation">(</span><span class="token parameter">value</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
	<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token function">isObject</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
		<span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
	<span class="token punctuation">}</span>
	<span class="token comment">// The use of `Object#toString` avoids issues with the `typeof` operator</span>
	<span class="token comment">// in Safari 9 which returns 'object' for typed arrays and other constructors.</span>
	<span class="token keyword">var</span> tag <span class="token operator">=</span> <span class="token function">baseGetTag</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token keyword">return</span> tag <span class="token operator">==</span> funcTag <span class="token operator">||</span> tag <span class="token operator">==</span> genTag <span class="token operator">||</span> tag <span class="token operator">==</span> asyncTag <span class="token operator">||</span> tag <span class="token operator">==</span> proxyTag<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><h3 id="_4-6-mixin-衍生的函数-arrayeach"><a href="#_4-6-mixin-衍生的函数-arrayeach" class="header-anchor">#</a> 4.6 mixin 衍生的函数 arrayEach</h3> <p>类似 [].forEarch</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">function</span> <span class="token function">arrayEach</span><span class="token punctuation">(</span><span class="token parameter">array<span class="token punctuation">,</span> iteratee</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
	<span class="token keyword">var</span> index <span class="token operator">=</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span>
		length <span class="token operator">=</span> array <span class="token operator">==</span> <span class="token keyword">null</span> <span class="token operator">?</span> <span class="token number">0</span> <span class="token operator">:</span> array<span class="token punctuation">.</span>length<span class="token punctuation">;</span>

	<span class="token keyword">while</span> <span class="token punctuation">(</span><span class="token operator">++</span>index <span class="token operator">&lt;</span> length<span class="token punctuation">)</span> <span class="token punctuation">{</span>
		<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">iteratee</span><span class="token punctuation">(</span>array<span class="token punctuation">[</span>index<span class="token punctuation">]</span><span class="token punctuation">,</span> index<span class="token punctuation">,</span> array<span class="token punctuation">)</span> <span class="token operator">===</span> <span class="token boolean">false</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
			<span class="token keyword">break</span><span class="token punctuation">;</span>
		<span class="token punctuation">}</span>
	<span class="token punctuation">}</span>
	<span class="token keyword">return</span> array<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><h3 id="_4-7-mixin-衍生的函数-arraypush"><a href="#_4-7-mixin-衍生的函数-arraypush" class="header-anchor">#</a> 4.7 mixin 衍生的函数 arrayPush</h3> <p>类似 [].push</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">function</span> <span class="token function">arrayPush</span><span class="token punctuation">(</span><span class="token parameter">array<span class="token punctuation">,</span> values</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
	<span class="token keyword">var</span> index <span class="token operator">=</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span>
		length <span class="token operator">=</span> values<span class="token punctuation">.</span>length<span class="token punctuation">,</span>
		offset <span class="token operator">=</span> array<span class="token punctuation">.</span>length<span class="token punctuation">;</span>

	<span class="token keyword">while</span> <span class="token punctuation">(</span><span class="token operator">++</span>index <span class="token operator">&lt;</span> length<span class="token punctuation">)</span> <span class="token punctuation">{</span>
	array<span class="token punctuation">[</span>offset <span class="token operator">+</span> index<span class="token punctuation">]</span> <span class="token operator">=</span> values<span class="token punctuation">[</span>index<span class="token punctuation">]</span><span class="token punctuation">;</span>
	<span class="token punctuation">}</span>
	<span class="token keyword">return</span> array<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><h3 id="_4-8-mixin-衍生的函数-copyarray"><a href="#_4-8-mixin-衍生的函数-copyarray" class="header-anchor">#</a> 4.8 mixin 衍生的函数 copyArray</h3> <p>拷贝数组</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">function</span> <span class="token function">copyArray</span><span class="token punctuation">(</span><span class="token parameter">source<span class="token punctuation">,</span> array</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
	<span class="token keyword">var</span> index <span class="token operator">=</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span>
		length <span class="token operator">=</span> source<span class="token punctuation">.</span>length<span class="token punctuation">;</span>

	array <span class="token operator">||</span> <span class="token punctuation">(</span>array <span class="token operator">=</span> <span class="token function">Array</span><span class="token punctuation">(</span>length<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token keyword">while</span> <span class="token punctuation">(</span><span class="token operator">++</span>index <span class="token operator">&lt;</span> length<span class="token punctuation">)</span> <span class="token punctuation">{</span>
		array<span class="token punctuation">[</span>index<span class="token punctuation">]</span> <span class="token operator">=</span> source<span class="token punctuation">[</span>index<span class="token punctuation">]</span><span class="token punctuation">;</span>
	<span class="token punctuation">}</span>
	<span class="token keyword">return</span> array<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div><h3 id="_4-9-mixin-源码解析"><a href="#_4-9-mixin-源码解析" class="header-anchor">#</a> 4.9 mixin 源码解析</h3> <p><code>lodash</code> 源码中两次调用 <code>mixin</code></p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// Add methods that return wrapped values in chain sequences.</span>
lodash<span class="token punctuation">.</span>after <span class="token operator">=</span> after<span class="token punctuation">;</span>
<span class="token comment">// code ... 等 153 个支持链式调用的方法</span>

<span class="token comment">// Add methods to `lodash.prototype`.</span>
<span class="token comment">// 把lodash上的静态方法赋值到 lodash.prototype 上</span>
<span class="token function">mixin</span><span class="token punctuation">(</span>lodash<span class="token punctuation">,</span> lodash<span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">// Add methods that return unwrapped values in chain sequences.</span>
lodash<span class="token punctuation">.</span>add <span class="token operator">=</span> add<span class="token punctuation">;</span>
<span class="token comment">// code ... 等 152 个不支持链式调用的方法</span>


<span class="token comment">// 这里其实就是过滤 after 等支持链式调用的方法，获取到 lodash 上的 add 等 添加到lodash.prototype 上。</span>
<span class="token function">mixin</span><span class="token punctuation">(</span>lodash<span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
	<span class="token keyword">var</span> source <span class="token operator">=</span> <span class="token punctuation">{</span><span class="token punctuation">}</span><span class="token punctuation">;</span>
	<span class="token comment">// baseForOwn 这里其实就是遍历lodash上的静态方法，执行回调函数</span>
	<span class="token function">baseForOwn</span><span class="token punctuation">(</span>lodash<span class="token punctuation">,</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">func<span class="token punctuation">,</span> methodName</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
		<span class="token comment">// 第一次 mixin 调用了所以赋值到了lodash.prototype</span>
		<span class="token comment">// 所以这里用 Object.hasOwnProperty 排除不在lodash.prototype 上的方法。也就是 add 等 152 个不支持链式调用的方法。</span>
		<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token function">hasOwnProperty</span><span class="token punctuation">.</span><span class="token function">call</span><span class="token punctuation">(</span>lodash<span class="token punctuation">.</span>prototype<span class="token punctuation">,</span> methodName<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
			source<span class="token punctuation">[</span>methodName<span class="token punctuation">]</span> <span class="token operator">=</span> func<span class="token punctuation">;</span>
		<span class="token punctuation">}</span>
	<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token keyword">return</span> source<span class="token punctuation">;</span>
<span class="token comment">// 最后一个参数options 特意注明不支持链式调用</span>
<span class="token punctuation">}</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> <span class="token string">'chain'</span><span class="token operator">:</span> <span class="token boolean">false</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><p>结合两次调用<code>mixin</code> 代入到源码解析如下
</p><details><summary>点击这里展开mixin源码及注释</summary><p></p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">function</span> <span class="token function">mixin</span><span class="token punctuation">(</span><span class="token parameter">object<span class="token punctuation">,</span> source<span class="token punctuation">,</span> options</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
	<span class="token comment">// source 对象中可以枚举的属性</span>
	<span class="token keyword">var</span> props <span class="token operator">=</span> <span class="token function">keys</span><span class="token punctuation">(</span>source<span class="token punctuation">)</span><span class="token punctuation">,</span>
		<span class="token comment">// source 对象中的方法名称数组</span>
		methodNames <span class="token operator">=</span> <span class="token function">baseFunctions</span><span class="token punctuation">(</span>source<span class="token punctuation">,</span> props<span class="token punctuation">)</span><span class="token punctuation">;</span>

	<span class="token keyword">if</span> <span class="token punctuation">(</span>options <span class="token operator">==</span> <span class="token keyword">null</span> <span class="token operator">&amp;&amp;</span>
		<span class="token operator">!</span><span class="token punctuation">(</span><span class="token function">isObject</span><span class="token punctuation">(</span>source<span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span> <span class="token punctuation">(</span>methodNames<span class="token punctuation">.</span>length <span class="token operator">||</span> <span class="token operator">!</span>props<span class="token punctuation">.</span>length<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
		<span class="token comment">// 如果 options 没传为 undefined  undefined == null 为true</span>
		<span class="token comment">// 且 如果source 不为 对象或者不是函数</span>
		<span class="token comment">// 且 source对象的函数函数长度 或者 source 对象的属性长度不为0</span>
		<span class="token comment">// 把 options 赋值为 source</span>
		options <span class="token operator">=</span> source<span class="token punctuation">;</span>
		<span class="token comment">// 把 source 赋值为 object</span>
		source <span class="token operator">=</span> object<span class="token punctuation">;</span>
		<span class="token comment">// 把 object 赋值为 this 也就是 _ (lodash)</span>
		object <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">;</span>
		<span class="token comment">// 获取到所有的方法名称数组</span>
		methodNames <span class="token operator">=</span> <span class="token function">baseFunctions</span><span class="token punctuation">(</span>source<span class="token punctuation">,</span> <span class="token function">keys</span><span class="token punctuation">(</span>source<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token punctuation">}</span>
	<span class="token comment">// 是否支持 链式调用</span>
	<span class="token comment">// options  不是对象或者不是函数，是null或者其他值</span>
	<span class="token comment">// 判断options是否是对象或者函数，如果不是或者函数则不会执行 'chain' in options 也就不会报错</span>
	<span class="token comment">//  且 chain 在 options的对象或者原型链中</span>
	<span class="token comment">// 知识点 in [MDN in :  https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/in</span>
	<span class="token comment">// 如果指定的属性在指定的对象或其原型链中，则in 运算符返回true。</span>

	<span class="token comment">// 或者 options.chain 转布尔值</span>
	<span class="token keyword">var</span> chain <span class="token operator">=</span> <span class="token operator">!</span><span class="token punctuation">(</span><span class="token function">isObject</span><span class="token punctuation">(</span>options<span class="token punctuation">)</span> <span class="token operator">&amp;&amp;</span> <span class="token string">'chain'</span> <span class="token keyword">in</span> options<span class="token punctuation">)</span> <span class="token operator">||</span> <span class="token operator">!</span><span class="token operator">!</span>options<span class="token punctuation">.</span>chain<span class="token punctuation">,</span>
		<span class="token comment">// object 是函数</span>
		isFunc <span class="token operator">=</span> <span class="token function">isFunction</span><span class="token punctuation">(</span>object<span class="token punctuation">)</span><span class="token punctuation">;</span>

	<span class="token comment">// 循环 方法名称数组</span>
	<span class="token function">arrayEach</span><span class="token punctuation">(</span>methodNames<span class="token punctuation">,</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">methodName</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
		<span class="token comment">// 函数本身</span>
		<span class="token keyword">var</span> func <span class="token operator">=</span> source<span class="token punctuation">[</span>methodName<span class="token punctuation">]</span><span class="token punctuation">;</span>
		<span class="token comment">// object 通常是 lodash  也赋值这个函数。</span>
		object<span class="token punctuation">[</span>methodName<span class="token punctuation">]</span> <span class="token operator">=</span> func<span class="token punctuation">;</span>
		<span class="token keyword">if</span> <span class="token punctuation">(</span>isFunc<span class="token punctuation">)</span> <span class="token punctuation">{</span>
			<span class="token comment">// 如果object是函数 赋值到  object prototype  上，通常是lodash</span>
			object<span class="token punctuation">.</span>prototype<span class="token punctuation">[</span>methodName<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
				<span class="token comment">// 实例上的__chain__ 属性 是否支持链式调用</span>
				<span class="token comment">// 这里的 this 是 new LodashWrapper 实例 类似如下</span>
				<span class="token comment">/**
				 {
					__actions__: [],
					__chain__: true
					__index__: 0
					__values__: undefined
					__wrapped__: []
				 }
				 **/</span>

				<span class="token keyword">var</span> chainAll <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>__chain__<span class="token punctuation">;</span>
				<span class="token comment">// options 中的 chain 属性 是否支持链式调用</span>
				<span class="token comment">// 两者有一个符合链式调用  执行下面的代码</span>
				<span class="token keyword">if</span> <span class="token punctuation">(</span>chain <span class="token operator">||</span> chainAll<span class="token punctuation">)</span> <span class="token punctuation">{</span>
					<span class="token comment">// 通常是 lodash</span>
					<span class="token keyword">var</span> result <span class="token operator">=</span> <span class="token function">object</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>__wrapped__<span class="token punctuation">)</span><span class="token punctuation">,</span>
					<span class="token comment">// 复制 实例上的 __action__ 到 result.__action__ 和 action 上</span>
					actions <span class="token operator">=</span> result<span class="token punctuation">.</span>__actions__ <span class="token operator">=</span> <span class="token function">copyArray</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>__actions__<span class="token punctuation">)</span><span class="token punctuation">;</span>

					<span class="token comment">// action 添加 函数 和 args 和 this 指向，延迟计算调用。</span>
					actions<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token punctuation">{</span> <span class="token string">'func'</span><span class="token operator">:</span> func<span class="token punctuation">,</span> <span class="token string">'args'</span><span class="token operator">:</span> arguments<span class="token punctuation">,</span> <span class="token string">'thisArg'</span><span class="token operator">:</span> object <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
					<span class="token comment">//实例上的__chain__ 属性  赋值给 result 的 属性 __chain__</span>
					result<span class="token punctuation">.</span>__chain__ <span class="token operator">=</span> chainAll<span class="token punctuation">;</span>
					<span class="token comment">// 最后返回这个实例</span>
					<span class="token keyword">return</span> result<span class="token punctuation">;</span>
				<span class="token punctuation">}</span>

				<span class="token comment">// 都不支持链式调用。直接调用</span>
				<span class="token comment">// 把当前实例的 value 和 arguments 对象 传递给 func 函数作为参数调用。返回调用结果。</span>
				<span class="token keyword">return</span> <span class="token function">func</span><span class="token punctuation">.</span><span class="token function">apply</span><span class="token punctuation">(</span>object<span class="token punctuation">,</span> <span class="token function">arrayPush</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">value</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">]</span><span class="token punctuation">,</span> arguments<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
			<span class="token punctuation">}</span><span class="token punctuation">;</span>
		<span class="token punctuation">}</span>
	<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

	<span class="token comment">// 最后返回对象 object</span>
	<span class="token keyword">return</span> object<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
</code></pre></div></details> <p>小结：简单说就是把<code>lodash</code>上的静态方法赋值到<code>lodash.prototype</code>上。分两次第一次是支持链式调用（<code>lodash.after</code>等 <code>153</code>个支持链式调用的方法），第二次是不支持链式调用的方法（<code>lodash.add</code>等<code>152</code>个不支持链式调用的方法）。</p> <h2 id="_5-lodash-究竟在-和-prototype挂载了多少方法和属性"><a href="#_5-lodash-究竟在-和-prototype挂载了多少方法和属性" class="header-anchor">#</a> 5. lodash 究竟在_和_.prototype挂载了多少方法和属性</h2> <p>再来看下<code>lodash</code>究竟挂载在<code>_</code>函数对象上有多少静态方法和属性，和挂载<code>_.prototype</code>上有多少方法和属性。</p> <p>使用<code>for in</code>循环一试便知。看如下代码：</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">var</span> staticMethods <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> staticProperty <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token keyword">for</span><span class="token punctuation">(</span><span class="token keyword">var</span> name <span class="token keyword">in</span> _<span class="token punctuation">)</span><span class="token punctuation">{</span>
	<span class="token keyword">if</span><span class="token punctuation">(</span><span class="token keyword">typeof</span> _<span class="token punctuation">[</span>name<span class="token punctuation">]</span> <span class="token operator">===</span> <span class="token string">'function'</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
		staticMethods<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span>name<span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token punctuation">}</span>
	<span class="token keyword">else</span><span class="token punctuation">{</span>
		staticProperty<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span>name<span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>staticProperty<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// [&quot;templateSettings&quot;, &quot;VERSION&quot;] 2个</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>staticMethods<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// [&quot;after&quot;, &quot;ary&quot;, &quot;assign&quot;, &quot;assignIn&quot;, &quot;assignInWith&quot;, ...] 305个</span>
</code></pre></div><p>其实就是上文提及的 <code>lodash.after</code> 等<code>153</code>个支持链式调用的函数 、<code>lodash.add</code> 等 <code>152</code>不支持链式调用的函数赋值而来。</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">var</span> prototypeMethods <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> prototypeProperty <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token keyword">for</span><span class="token punctuation">(</span><span class="token keyword">var</span> name <span class="token keyword">in</span> <span class="token class-name">_</span><span class="token punctuation">.</span>prototype<span class="token punctuation">)</span><span class="token punctuation">{</span>
	<span class="token keyword">if</span><span class="token punctuation">(</span><span class="token keyword">typeof</span> <span class="token class-name">_</span><span class="token punctuation">.</span>prototype<span class="token punctuation">[</span>name<span class="token punctuation">]</span> <span class="token operator">===</span> <span class="token string">'function'</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
		prototypeMethods<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span>name<span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token punctuation">}</span>
	<span class="token keyword">else</span><span class="token punctuation">{</span>
		prototypeProperty<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span>name<span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>prototypeProperty<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// []</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>prototypeMethods<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// [&quot;after&quot;, &quot;all&quot;, &quot;allKeys&quot;, &quot;any&quot;, &quot;assign&quot;, ...] 317个</span>
</code></pre></div><p>相比<code>lodash</code>上的静态方法多了<code>12</code>个，说明除了 <code>mixin</code> 外，还有<code>12</code>个其他形式赋值而来。</p> <p>支持链式调用的方法最后返回是实例对象，获取最后的处理的结果值，最后需要调用<code>value</code>方法。</p> <p>笔者画了一张表示<code>lodash</code>的方法和属性挂载关系图。</p> <p><img src="/assets/img/lodash-v4.17.15-lodash.prototype-mixin.d4e32ad2.png" alt="的方法和属性挂载关系图"></p> <h2 id="_6-请出贯穿下文的简单的例子"><a href="#_6-请出贯穿下文的简单的例子" class="header-anchor">#</a> 6. 请出贯穿下文的简单的例子</h2> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">var</span> result <span class="token operator">=</span> _<span class="token punctuation">.</span><span class="token function">chain</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token parameter">el</span> <span class="token operator">=&gt;</span> <span class="token punctuation">{</span>
	console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>el<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 1, 2, 3</span>
	<span class="token keyword">return</span> el <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">take</span><span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">value</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// lodash中这里的`map`仅执行了`3`次。</span>
<span class="token comment">// 具体功能也很简单 数组 1-5 加一，最后获取其中三个值。</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'result:'</span><span class="token punctuation">,</span> result<span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><p><strong>也就是说这里<code>lodash</code>聪明的知道了最后需要几个值，就执行几次<code>map</code>循环，对于很大的数组，提升性能很有帮助。</strong><br>
而<code>underscore</code>执行这段代码其中<code>map</code>执行了5次。
如果是平常实现该功能也简单。</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">var</span> result <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">]</span><span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token parameter">el</span> <span class="token operator">=&gt;</span> el <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">slice</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'result:'</span><span class="token punctuation">,</span> result<span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><p>而相比<code>lodash</code>这里的<code>map</code>执行了<code>5</code>次。</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// 不使用 map、slice</span>
<span class="token keyword">var</span> result <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> arr <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">var</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> <span class="token number">3</span><span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span><span class="token punctuation">{</span>
	result<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">=</span> arr<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>result<span class="token punctuation">,</span> <span class="token string">'result'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><p>简单说这里的<code>map</code>方法，添加 <code>LazyWrapper</code> 的方法到 <code>lodash.prototype</code>存储下来，最后调用 <code>value</code>时再调用。
具体看下文源码实现。</p> <h2 id="_7-添加-lazywrapper-的方法到-lodash-prototype"><a href="#_7-添加-lazywrapper-的方法到-lodash-prototype" class="header-anchor">#</a> 7. 添加 <code>LazyWrapper</code> 的方法到 <code>lodash.prototype</code></h2> <p>主要是如下方法添加到到 <code>lodash.prototype</code> 原型上。</p> <div class="language- extra-class"><pre class="language-text"><code>// &quot;constructor&quot;
[&quot;drop&quot;, &quot;dropRight&quot;, &quot;take&quot;, &quot;takeRight&quot;, &quot;filter&quot;, &quot;map&quot;, &quot;takeWhile&quot;, &quot;head&quot;, &quot;last&quot;, &quot;initial&quot;, &quot;tail&quot;, &quot;compact&quot;, &quot;find&quot;, &quot;findLast&quot;, &quot;invokeMap&quot;, &quot;reject&quot;, &quot;slice&quot;, &quot;takeRightWhile&quot;, &quot;toArray&quot;, &quot;clone&quot;, &quot;reverse&quot;, &quot;value&quot;]
</code></pre></div><details><summary>点击这里展开具体源码及注释</summary> <div class="language-js extra-class"><pre class="language-js"><code><span class="token comment">// Add `LazyWrapper` methods to `lodash.prototype`.</span>
<span class="token comment">// baseForOwn 这里其实就是遍历LazyWrapper.prototype上的方法，执行回调函数</span>
<span class="token function">baseForOwn</span><span class="token punctuation">(</span><span class="token class-name">LazyWrapper</span><span class="token punctuation">.</span>prototype<span class="token punctuation">,</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">func<span class="token punctuation">,</span> methodName</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
	<span class="token comment">// 检测函数名称是否是迭代器也就是循环</span>
	<span class="token keyword">var</span> checkIteratee <span class="token operator">=</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">^(?:filter|find|map|reject)|While$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">.</span><span class="token function">test</span><span class="token punctuation">(</span>methodName<span class="token punctuation">)</span><span class="token punctuation">,</span>
		<span class="token comment">// 检测函数名称是否head和last</span>
		<span class="token comment">// 顺便提一下 ()这个是捕获分组 而加上 ?:  则是非捕获分组 也就是说不用于其他操作</span>
		isTaker <span class="token operator">=</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">^(?:head|last)$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">.</span><span class="token function">test</span><span class="token punctuation">(</span>methodName<span class="token punctuation">)</span><span class="token punctuation">,</span>
		<span class="token comment">// lodashFunc 是 根据 isTaker 组合 takeRight take methodName</span>
		lodashFunc <span class="token operator">=</span> lodash<span class="token punctuation">[</span>isTaker <span class="token operator">?</span> <span class="token punctuation">(</span><span class="token string">'take'</span> <span class="token operator">+</span> <span class="token punctuation">(</span>methodName <span class="token operator">==</span> <span class="token string">'last'</span> <span class="token operator">?</span> <span class="token string">'Right'</span> <span class="token operator">:</span> <span class="token string">''</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">:</span> methodName<span class="token punctuation">]</span><span class="token punctuation">,</span>
		<span class="token comment">// 根据isTaker 和 是 find 判断结果是否 包装</span>
		retUnwrapped <span class="token operator">=</span> isTaker <span class="token operator">||</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">^find</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">.</span><span class="token function">test</span><span class="token punctuation">(</span>methodName<span class="token punctuation">)</span><span class="token punctuation">;</span>

	<span class="token comment">// 如果不存在这个函数，就不往下执行</span>
	<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>lodashFunc<span class="token punctuation">)</span> <span class="token punctuation">{</span>
		<span class="token keyword">return</span><span class="token punctuation">;</span>
	<span class="token punctuation">}</span>
	<span class="token comment">// 把 lodash.prototype 方法赋值到lodash.prototype</span>
	lodash<span class="token punctuation">.</span>prototype<span class="token punctuation">[</span>methodName<span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
		<span class="token comment">// 取实例中的__wrapped__ 值 例子中则是 [1,2,3,4,5]</span>
		<span class="token keyword">var</span> value <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>__wrapped__<span class="token punctuation">,</span>
			<span class="token comment">// 如果是head和last 方法 isTaker 返回 [1], 否则是arguments对象</span>
			args <span class="token operator">=</span> isTaker <span class="token operator">?</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span> <span class="token operator">:</span> arguments<span class="token punctuation">,</span>
			<span class="token comment">// 如果value 是LayeWrapper的实例</span>
			isLazy <span class="token operator">=</span> value <span class="token keyword">instanceof</span> <span class="token class-name">LazyWrapper</span><span class="token punctuation">,</span>
			<span class="token comment">// 迭代器 循环</span>
			iteratee <span class="token operator">=</span> args<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
			<span class="token comment">// 使用useLazy isLazy value或者是数组</span>
			useLazy <span class="token operator">=</span> isLazy <span class="token operator">||</span> <span class="token function">isArray</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span><span class="token punctuation">;</span>

		<span class="token keyword">var</span> <span class="token function-variable function">interceptor</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">value</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
			<span class="token comment">// 函数执行 value args 组合成数组参数</span>
			<span class="token keyword">var</span> result <span class="token operator">=</span> <span class="token function">lodashFunc</span><span class="token punctuation">.</span><span class="token function">apply</span><span class="token punctuation">(</span>lodash<span class="token punctuation">,</span> <span class="token function">arrayPush</span><span class="token punctuation">(</span><span class="token punctuation">[</span>value<span class="token punctuation">]</span><span class="token punctuation">,</span> args<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
			<span class="token comment">// 如果是 head 和 last (isTaker) 支持链式调用 返回结果的第一个参数 否则 返回result</span>
			<span class="token keyword">return</span> <span class="token punctuation">(</span>isTaker <span class="token operator">&amp;&amp;</span> chainAll<span class="token punctuation">)</span> <span class="token operator">?</span> result<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span> <span class="token operator">:</span> result<span class="token punctuation">;</span>
		<span class="token punctuation">}</span><span class="token punctuation">;</span>

		<span class="token comment">// useLazy true 并且 函数checkIteratee 且迭代器是函数，且迭代器参数个数不等于1</span>
		<span class="token keyword">if</span> <span class="token punctuation">(</span>useLazy <span class="token operator">&amp;&amp;</span> checkIteratee <span class="token operator">&amp;&amp;</span> <span class="token keyword">typeof</span> iteratee <span class="token operator">==</span> <span class="token string">'function'</span> <span class="token operator">&amp;&amp;</span> iteratee<span class="token punctuation">.</span>length <span class="token operator">!=</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
			<span class="token comment">// Avoid lazy use if the iteratee has a &quot;length&quot; value other than `1`.</span>
			<span class="token comment">// useLazy 赋值为 false</span>
			<span class="token comment">// isLazy 赋值为 false</span>
			isLazy <span class="token operator">=</span> useLazy <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
		<span class="token punctuation">}</span>
		<span class="token comment">// 取实例上的 __chain__</span>
		<span class="token keyword">var</span> chainAll <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>__chain__<span class="token punctuation">,</span>
			<span class="token comment">// 存储的待执行的函数 __actions__ 二次取反是布尔值 也就是等于0或者大于0两种结果</span>
			isHybrid <span class="token operator">=</span> <span class="token operator">!</span><span class="token operator">!</span><span class="token keyword">this</span><span class="token punctuation">.</span>__actions__<span class="token punctuation">.</span>length<span class="token punctuation">,</span>
			<span class="token comment">// 是否不包装 用结果是否不包装 且 不支持链式调用</span>
			isUnwrapped <span class="token operator">=</span> retUnwrapped <span class="token operator">&amp;&amp;</span> <span class="token operator">!</span>chainAll<span class="token punctuation">,</span>
			<span class="token comment">// 是否仅Lazy 用isLazy 和 存储的函数</span>
			onlyLazy <span class="token operator">=</span> isLazy <span class="token operator">&amp;&amp;</span> <span class="token operator">!</span>isHybrid<span class="token punctuation">;</span>

		<span class="token comment">// 结果不包装 且 useLazy 为 true</span>
		<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>retUnwrapped <span class="token operator">&amp;&amp;</span> useLazy<span class="token punctuation">)</span> <span class="token punctuation">{</span>
			<span class="token comment">// 实例 new LazyWrapper 这里的this 是 new LodashWrapper()</span>
			value <span class="token operator">=</span> onlyLazy <span class="token operator">?</span> value <span class="token operator">:</span> <span class="token keyword">new</span> <span class="token class-name">LazyWrapper</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
			<span class="token comment">// result 执行函数结果</span>
			<span class="token keyword">var</span> result <span class="token operator">=</span> <span class="token function">func</span><span class="token punctuation">.</span><span class="token function">apply</span><span class="token punctuation">(</span>value<span class="token punctuation">,</span> args<span class="token punctuation">)</span><span class="token punctuation">;</span>

			<span class="token comment">/*
			*
			// _.thru(value, interceptor)
			// 这个方法类似 _.tap， 除了它返回 interceptor 的返回结果。该方法的目的是&quot;传递&quot; 值到一个方法链序列以取代中间结果。
			_([1, 2, 3])
			.tap(function(array) {
				// 改变传入的数组
				array.pop();
			})
			.reverse()
			.value();
			// =&gt; [2, 1]
			*/</span>

			<span class="token comment">// thisArg 指向undefined 或者null 非严格模式下是指向window，严格模式是undefined 或者nll</span>
			result<span class="token punctuation">.</span>__actions__<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token punctuation">{</span> <span class="token string">'func'</span><span class="token operator">:</span> thru<span class="token punctuation">,</span> <span class="token string">'args'</span><span class="token operator">:</span> <span class="token punctuation">[</span>interceptor<span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token string">'thisArg'</span><span class="token operator">:</span> <span class="token keyword">undefined</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
			<span class="token comment">// 返回实例 lodashWrapper</span>
			<span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">LodashWrapper</span><span class="token punctuation">(</span>result<span class="token punctuation">,</span> chainAll<span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token punctuation">}</span>
		<span class="token comment">// 不包装 且 onlyLazy 为 true</span>
		<span class="token keyword">if</span> <span class="token punctuation">(</span>isUnwrapped <span class="token operator">&amp;&amp;</span> onlyLazy<span class="token punctuation">)</span> <span class="token punctuation">{</span>
			<span class="token comment">// 执行函数</span>
			<span class="token keyword">return</span> <span class="token function">func</span><span class="token punctuation">.</span><span class="token function">apply</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">,</span> args<span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token punctuation">}</span>
		<span class="token comment">// 上面都没有执行，执行到这里了</span>
		<span class="token comment">// 执行 thru 函数，回调函数 是 interceptor</span>
		result <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">thru</span><span class="token punctuation">(</span>interceptor<span class="token punctuation">)</span><span class="token punctuation">;</span>
		<span class="token keyword">return</span> isUnwrapped <span class="token operator">?</span> <span class="token punctuation">(</span>isTaker <span class="token operator">?</span> result<span class="token punctuation">.</span><span class="token function">value</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span> <span class="token operator">:</span> result<span class="token punctuation">.</span><span class="token function">value</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">:</span> result<span class="token punctuation">;</span>
	<span class="token punctuation">}</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div></details> <p>小结一下，写了这么多注释，简单说：其实就是用<code>LazyWrapper.prototype</code> 改写原先在<code>lodash.prototype</code>的函数，判断函数是否需要使用惰性求值，需要时再调用。</p> <p><strong>读者可以断点调试一下，善用断点进入函数功能，对着注释看，可能会更加清晰。</strong></p><details><summary>点击查看断点调试的部分截图</summary><p></p> <p><img src="/assets/img/demo-chain-map-result-debugger.fe494628.png" alt="例子的chain和map执行后的debugger截图"> <img src="/assets/img/demo-chain-map-result.06c41dca.png" alt="例子的chain和map执行后的结果截图"></p></details> <p>链式调用最后都是返回实例对象，实际的处理数据的函数都没有调用，而是被存储存储下来了，最后调用<code>value</code>方法，才执行这些函数。</p> <h2 id="_8-lodash-prototype-value-即-wrappervalue"><a href="#_8-lodash-prototype-value-即-wrappervalue" class="header-anchor">#</a> 8. lodash.prototype.value 即 wrapperValue</h2> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">function</span> <span class="token function">baseWrapperValue</span><span class="token punctuation">(</span><span class="token parameter">value<span class="token punctuation">,</span> actions</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
	<span class="token keyword">var</span> result <span class="token operator">=</span> value<span class="token punctuation">;</span>
	<span class="token comment">// 如果是lazyWrapper的实例，则调用LazyWrapper.prototype.value 方法，也就是 lazyValue 方法</span>
	<span class="token keyword">if</span> <span class="token punctuation">(</span>result <span class="token keyword">instanceof</span> <span class="token class-name">LazyWrapper</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
		result <span class="token operator">=</span> result<span class="token punctuation">.</span><span class="token function">value</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token punctuation">}</span>
	<span class="token comment">// 类似 [].reduce()，把上一个函数返回结果作为参数传递给下一个函数</span>
	<span class="token keyword">return</span> <span class="token function">arrayReduce</span><span class="token punctuation">(</span>actions<span class="token punctuation">,</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">result<span class="token punctuation">,</span> action</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
		<span class="token keyword">return</span> action<span class="token punctuation">.</span><span class="token function">func</span><span class="token punctuation">.</span><span class="token function">apply</span><span class="token punctuation">(</span>action<span class="token punctuation">.</span>thisArg<span class="token punctuation">,</span> <span class="token function">arrayPush</span><span class="token punctuation">(</span><span class="token punctuation">[</span>result<span class="token punctuation">]</span><span class="token punctuation">,</span> action<span class="token punctuation">.</span>args<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token punctuation">}</span><span class="token punctuation">,</span> result<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">function</span> <span class="token function">wrapperValue</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
	<span class="token keyword">return</span> <span class="token function">baseWrapperValue</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>__wrapped__<span class="token punctuation">,</span> <span class="token keyword">this</span><span class="token punctuation">.</span>__actions__<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
lodash<span class="token punctuation">.</span>prototype<span class="token punctuation">.</span>toJSON <span class="token operator">=</span> lodash<span class="token punctuation">.</span>prototype<span class="token punctuation">.</span>valueOf <span class="token operator">=</span> lodash<span class="token punctuation">.</span>prototype<span class="token punctuation">.</span>value <span class="token operator">=</span> wrapperValue<span class="token punctuation">;</span>
</code></pre></div><p>如果是惰性求值，则调用的是 <code>LazyWrapper.prototype.value</code> 即 <code>lazyValue</code>。</p> <h2 id="_9-lazywrapper-prototype-value-即-lazyvalue-惰性求值"><a href="#_9-lazywrapper-prototype-value-即-lazyvalue-惰性求值" class="header-anchor">#</a> 9. LazyWrapper.prototype.value 即 lazyValue 惰性求值</h2> <details><summary>点击这里展开lazyValue源码及注释</summary> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">function</span> <span class="token function">LazyWrapper</span><span class="token punctuation">(</span><span class="token parameter">value</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
	<span class="token comment">// 参数 value</span>
	<span class="token keyword">this</span><span class="token punctuation">.</span>__wrapped__ <span class="token operator">=</span> value<span class="token punctuation">;</span>
	<span class="token comment">// 执行的函数</span>
	<span class="token keyword">this</span><span class="token punctuation">.</span>__actions__ <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
	<span class="token keyword">this</span><span class="token punctuation">.</span>__dir__ <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span>
	<span class="token comment">// 过滤</span>
	<span class="token keyword">this</span><span class="token punctuation">.</span>__filtered__ <span class="token operator">=</span> <span class="token boolean">false</span><span class="token punctuation">;</span>
	<span class="token comment">// 存储迭代器函数</span>
	<span class="token keyword">this</span><span class="token punctuation">.</span>__iteratees__ <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
	<span class="token comment">// 默认最大取值个数</span>
	<span class="token keyword">this</span><span class="token punctuation">.</span>__takeCount__ <span class="token operator">=</span> <span class="token constant">MAX_ARRAY_LENGTH</span><span class="token punctuation">;</span>
	<span class="token comment">// 具体取值多少个，存储函数和类型</span>
	<span class="token keyword">this</span><span class="token punctuation">.</span>__views__ <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">/**
* Extracts the unwrapped value from its lazy wrapper.
*
* @private
* @name value
* @memberOf LazyWrapper
* @returns {*} Returns the unwrapped value.
*/</span>
<span class="token keyword">function</span> <span class="token function">lazyValue</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
	<span class="token comment">// this.__wrapped__ 是 new LodashWrapper 实例 所以执行.value 获取原始值</span>
	<span class="token keyword">var</span> array <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>__wrapped__<span class="token punctuation">.</span><span class="token function">value</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
		<span class="token comment">//</span>
		dir <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>__dir__<span class="token punctuation">,</span>
		<span class="token comment">// 是否是函数</span>
		isArr <span class="token operator">=</span> <span class="token function">isArray</span><span class="token punctuation">(</span>array<span class="token punctuation">)</span><span class="token punctuation">,</span>
		<span class="token comment">// 是否从右边开始</span>
		isRight <span class="token operator">=</span> dir <span class="token operator">&lt;</span> <span class="token number">0</span><span class="token punctuation">,</span>
		<span class="token comment">// 数组的长度。如果不是数组，则是0</span>
		arrLength <span class="token operator">=</span> isArr <span class="token operator">?</span> array<span class="token punctuation">.</span>length <span class="token operator">:</span> <span class="token number">0</span><span class="token punctuation">,</span>
		<span class="token comment">// 获取 take(3) 上述例子中 则是 start: 0，end: 3</span>
		view <span class="token operator">=</span> <span class="token function">getView</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> arrLength<span class="token punctuation">,</span> <span class="token keyword">this</span><span class="token punctuation">.</span>__views__<span class="token punctuation">)</span><span class="token punctuation">,</span>
		start <span class="token operator">=</span> view<span class="token punctuation">.</span>start<span class="token punctuation">,</span>
		end <span class="token operator">=</span> view<span class="token punctuation">.</span>end<span class="token punctuation">,</span>
		<span class="token comment">// 长度 3</span>
		length <span class="token operator">=</span> end <span class="token operator">-</span> start<span class="token punctuation">,</span>
		<span class="token comment">// 如果是是从右开始</span>
		index <span class="token operator">=</span> isRight <span class="token operator">?</span> end <span class="token operator">:</span> <span class="token punctuation">(</span>start <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">,</span>
		<span class="token comment">// 存储的迭代器数组</span>
		iteratees <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>__iteratees__<span class="token punctuation">,</span>
		<span class="token comment">// 迭代器数组长度</span>
		iterLength <span class="token operator">=</span> iteratees<span class="token punctuation">.</span>length<span class="token punctuation">,</span>
		<span class="token comment">// 结果resIndex</span>
		resIndex <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">,</span>
		<span class="token comment">// 最后获取几个值，也就是 3</span>
		takeCount <span class="token operator">=</span> <span class="token function">nativeMin</span><span class="token punctuation">(</span>length<span class="token punctuation">,</span> <span class="token keyword">this</span><span class="token punctuation">.</span>__takeCount__<span class="token punctuation">)</span><span class="token punctuation">;</span>

	<span class="token comment">// 如果不是数组，或者 不是从右开始 并且 参数数组长度等于take的长度 takeCount等于长度</span>
	<span class="token comment">// 则直接调用 baseWrapperValue 不需要</span>
	<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>isArr <span class="token operator">||</span> <span class="token punctuation">(</span><span class="token operator">!</span>isRight <span class="token operator">&amp;&amp;</span> arrLength <span class="token operator">==</span> length <span class="token operator">&amp;&amp;</span> takeCount <span class="token operator">==</span> length<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
		<span class="token keyword">return</span> <span class="token function">baseWrapperValue</span><span class="token punctuation">(</span>array<span class="token punctuation">,</span> <span class="token keyword">this</span><span class="token punctuation">.</span>__actions__<span class="token punctuation">)</span><span class="token punctuation">;</span>
	<span class="token punctuation">}</span>
	<span class="token keyword">var</span> result <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span>

	<span class="token comment">// 标签语句 label</span>
	<span class="token comment">// MDN label 链接</span>
	<span class="token comment">// https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/label</span>
	<span class="token comment">// 标记语句可以和 break 或 continue 语句一起使用。标记就是在一条语句前面加个可以引用的标识符（identifier）。</span>
	outer<span class="token operator">:</span>
	<span class="token keyword">while</span> <span class="token punctuation">(</span>length<span class="token operator">--</span> <span class="token operator">&amp;&amp;</span> resIndex <span class="token operator">&lt;</span> takeCount<span class="token punctuation">)</span> <span class="token punctuation">{</span>
		index <span class="token operator">+=</span> dir<span class="token punctuation">;</span>

		<span class="token keyword">var</span> iterIndex <span class="token operator">=</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">,</span>
			<span class="token comment">// 数组第一项</span>
			value <span class="token operator">=</span> array<span class="token punctuation">[</span>index<span class="token punctuation">]</span><span class="token punctuation">;</span>

		<span class="token keyword">while</span> <span class="token punctuation">(</span><span class="token operator">++</span>iterIndex <span class="token operator">&lt;</span> iterLength<span class="token punctuation">)</span> <span class="token punctuation">{</span>
			<span class="token comment">// 迭代器数组 {iteratee: function{}, typy: 2}</span>
			<span class="token keyword">var</span> data <span class="token operator">=</span> iteratees<span class="token punctuation">[</span>iterIndex<span class="token punctuation">]</span><span class="token punctuation">,</span>
				iteratee <span class="token operator">=</span> data<span class="token punctuation">.</span>iteratee<span class="token punctuation">,</span>
				type <span class="token operator">=</span> data<span class="token punctuation">.</span>type<span class="token punctuation">,</span>
				<span class="token comment">// 结果 迭代器执行结果</span>
				computed <span class="token operator">=</span> <span class="token function">iteratee</span><span class="token punctuation">(</span>value<span class="token punctuation">)</span><span class="token punctuation">;</span>

			<span class="token keyword">if</span> <span class="token punctuation">(</span>type <span class="token operator">==</span> <span class="token constant">LAZY_MAP_FLAG</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
				<span class="token comment">// 如果 type 是 map 类型，结果 computed 赋值给value</span>
				value <span class="token operator">=</span> computed<span class="token punctuation">;</span>
			<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>computed<span class="token punctuation">)</span> <span class="token punctuation">{</span>
				<span class="token keyword">if</span> <span class="token punctuation">(</span>type <span class="token operator">==</span> <span class="token constant">LAZY_FILTER_FLAG</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
					<span class="token comment">// 退出当前这次循环，进行下一次循环</span>
					<span class="token keyword">continue</span> outer<span class="token punctuation">;</span>
				<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
					<span class="token comment">// 退出整个循环</span>
					<span class="token keyword">break</span> outer<span class="token punctuation">;</span>
				<span class="token punctuation">}</span>
			<span class="token punctuation">}</span>
		<span class="token punctuation">}</span>
		<span class="token comment">// 最终数组</span>
		result<span class="token punctuation">[</span>resIndex<span class="token operator">++</span><span class="token punctuation">]</span> <span class="token operator">=</span> value<span class="token punctuation">;</span>
	<span class="token punctuation">}</span>
	<span class="token comment">// 返回数组 例子中则是 [2, 3, 4]</span>
	<span class="token keyword">return</span> result<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// Ensure `LazyWrapper` is an instance of `baseLodash`.</span>
<span class="token class-name">LazyWrapper</span><span class="token punctuation">.</span>prototype <span class="token operator">=</span> <span class="token function">baseCreate</span><span class="token punctuation">(</span>baseLodash<span class="token punctuation">.</span>prototype<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token class-name">LazyWrapper</span><span class="token punctuation">.</span>prototype<span class="token punctuation">.</span>constructor <span class="token operator">=</span> LazyWrapper<span class="token punctuation">;</span>

<span class="token class-name">LazyWrapper</span><span class="token punctuation">.</span>prototype<span class="token punctuation">.</span>value <span class="token operator">=</span> lazyValue<span class="token punctuation">;</span>
</code></pre></div></details> <p>笔者画了一张 <code>lodash</code>和<code>LazyWrapper</code>的关系图来表示。
<img src="/assets/img/lodash-v4.17.15-LazyWrapper.prototype.49da6e57.png" alt="和的关系图"></p> <p>小结：<code>lazyValue</code>简单说实现的功能就是把之前记录的需要执行几次，把记录存储的函数执行几次，不会有多少项数据就执行多少次，而是根据需要几项，执行几项。
也就是说以下这个例子中，<code>map</code>函数只会执行<code>3</code>次。如果没有用惰性求值，那么<code>map</code>函数会执行<code>5</code>次。</p> <div class="language-js extra-class"><pre class="language-js"><code><span class="token keyword">var</span> result <span class="token operator">=</span> _<span class="token punctuation">.</span><span class="token function">chain</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">]</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token parameter">el</span> <span class="token operator">=&gt;</span> el <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">take</span><span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">)</span>
<span class="token punctuation">.</span><span class="token function">value</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
</code></pre></div><h2 id="_10-总结"><a href="#_10-总结" class="header-anchor">#</a> 10. 总结</h2> <p>行文至此，基本接近尾声，最后总结一下。</p> <blockquote><p>文章主要学习了<code>runInContext()</code> 导出<code>_</code> <code>lodash</code>函数使用<code>baseCreate</code>方法原型继承<code>LodashWrapper</code>和<code>LazyWrapper</code>，<code>mixin</code>挂载方法到<code>lodash.prototype</code>、后文用结合例子解释<code>lodash.prototype.value(wrapperValue)</code>和<code>Lazy.prototype.value(lazyValue)</code>惰性求值的源码具体实现。</p></blockquote> <p><strong>分享一个只知道函数名找源码定位函数申明位置的<code>VSCode</code> 技巧</strong>：<code>Ctrl + p</code>。输入 <code>@functionName</code> 定位函数<code>functionName</code>在源码文件中的具体位置。如果知道调用位置，那直接按<code>alt+鼠标左键</code>即可跳转到函数申明的位置。</p> <p>如果读者发现有不妥或可改善之处，再或者哪里没写明白的地方，欢迎评论指出。另外觉得写得不错，对您有些许帮助，可以点赞、评论、转发分享，也是对笔者的一种支持。万分感谢。</p> <h2 id="_11-推荐阅读"><a href="#_11-推荐阅读" class="header-anchor">#</a> 11. 推荐阅读</h2> <p><a href="https://github.com/lodash/lodash" target="_blank" rel="noopener noreferrer">lodash github仓库<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a><br> <a href="https://lodash.com/docs/4.17.15" target="_blank" rel="noopener noreferrer">lodash 官方文档<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a><br> <a href="https://lodashjs.com/" target="_blank" rel="noopener noreferrer">lodash 中文文档<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a><br> <a href="http://blog.zollty.com/b/archive/create-a-front-end-tool-library.html" target="_blank" rel="noopener noreferrer">打造一个类似于lodash的前端工具库<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a><br> <a href="https://juejin.im/post/5b784baf51882542ed141a84" target="_blank" rel="noopener noreferrer">惰性求值——lodash源码解读<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a><br> <a href="https://zhuanlan.zhihu.com/p/24138694" target="_blank" rel="noopener noreferrer">luobo tang：lazy.js 惰性求值实现分析<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a><br> <a href="https://github.com/dtao/lazy.js" target="_blank" rel="noopener noreferrer">lazy.js github 仓库<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a><br> <a href="https://unpkg.com/lodash@4.17.15/lodash.js" target="_blank" rel="noopener noreferrer">本文章学习的<code>lodash</code>的版本<code>v4.17.15</code> <code>unpkg.com</code>链接<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a><br></p> <h2 id="笔者往期文章"><a href="#笔者往期文章" class="header-anchor">#</a> 笔者往期文章</h2> <p><a href="https://juejin.im/post/5c433e216fb9a049c15f841b" target="_blank" rel="noopener noreferrer">面试官问：JS的继承<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a><br> <a href="https://juejin.im/post/5c0c87b35188252e8966c78a" target="_blank" rel="noopener noreferrer">面试官问：JS的this指向<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a><br> <a href="https://juejin.im/post/5bf6c79bf265da6142738b29" target="_blank" rel="noopener noreferrer">面试官问：能否模拟实现JS的call和apply方法<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a><br> <a href="https://juejin.im/post/5bec4183f265da616b1044d7" target="_blank" rel="noopener noreferrer">面试官问：能否模拟实现JS的bind方法<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a><br> <a href="https://juejin.im/post/5bde7c926fb9a049f66b8b52" target="_blank" rel="noopener noreferrer">面试官问：能否模拟实现JS的new操作符<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a><br> <a href="https://juejin.im/post/5b86732451882542af1c8082" target="_blank" rel="noopener noreferrer">前端使用puppeteer 爬虫生成《React.js 小书》PDF并合并<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a></p> <h2 id="关于"><a href="#关于" class="header-anchor">#</a> 关于</h2> <p>作者：常以<strong>若川</strong>为名混迹于江湖。前端路上 | PPT爱好者 | 所知甚少，唯善学。<br> <a href="https://lxchuan12.gitee.io" target="_blank" rel="noopener noreferrer">若川的博客<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a>，使用<code>vuepress</code>重构了，阅读体验可能更好些<br> <a href="https://juejin.im/user/1415826704971918/posts" target="_blank" rel="noopener noreferrer">掘金专栏<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a>，欢迎关注~<br> <a href="https://segmentfault.com/blog/lxchuan12" target="_blank" rel="noopener noreferrer"><code>segmentfault</code>前端视野专栏<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a>，欢迎关注~<br> <a href="https://zhuanlan.zhihu.com/lxchuan12" target="_blank" rel="noopener noreferrer">知乎前端视野专栏<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a>，欢迎关注~<br> <a href="https://www.yuque.com/lxchuan12/blog" target="_blank" rel="noopener noreferrer">语雀前端视野专栏<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a>，新增语雀专栏，欢迎关注~<br> <a href="https://github.com/lxchuan12/blog" target="_blank" rel="noopener noreferrer">github blog<span><svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15" class="icon outbound"><path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path> <polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon></svg> <span class="sr-only">(opens new window)</span></span></a>，相关源码和资源都放在这里，求个<code>star</code>^_^~</p> <h2 id="微信公众号-若川视野"><a href="#微信公众号-若川视野" class="header-anchor">#</a> 微信公众号  若川视野</h2> <p>可能比较有趣的微信公众号，长按扫码关注（<strong>回复pdf获取前端优质书籍pdf</strong>）。欢迎加笔者微信<code>ruochuan12</code>（注明来源，基本来者不拒），拉您进【前端视野交流群】，长期交流学习~</p> <p><img src="/assets/img/wechat-official-accounts-mini.d9491f62.png" alt="若川视野"></p></div> <footer class="page-edit"><!----> <div class="last-updated"><span class="prefix">最后更新时间:</span> <span class="time">4/3/2021, 4:12:45 PM</span></div></footer> <div class="page-nav"><p class="inner"><span class="prev">
      ←
      <a href="/sentry/" class="prev">
        学习 sentry 源码整体架构，打造属于自己的前端异常监控SDK
      </a></span> <span class="next"><a href="/underscore/">
        学习underscore源码整体架构，打造属于自己的函数式编程类库
      </a>
      →
    </span></p></div> </main></div><div class="global-ui"><BackToTop></BackToTop><!----></div></div>
    <script src="/assets/js/app.9fbcafa6.js" defer></script><script src="/assets/js/2.33539d56.js" defer></script><script src="/assets/js/11.599e7eee.js" defer></script><script src="/assets/js/23.72249401.js" defer></script>
  </body>
</html>
